import random
from bs4 import BeautifulSoup
import pickle
import datetime
import os
import sys
from prettytable import PrettyTable
import json
import requests


# 是否为数字
def num_judge(num):
    try:
        num_test = int(num)
        return True
    except:
        return False


def num_Range(num):
    if int(num) > 0 and int(num) < 5:
        return True
    else:
        return False


def class_pretty():
    x = PrettyTable(["序号", "操作"])
    x.align["序号"] = "2"
    x.padding_width = 1
    x.add_row(["1", '更新代理'])
    x.add_row(["2", '查询最近'])
    x.add_row(["3", '查询所有'])
    x.add_row(["4", '日期查询'])
    print(x)


# pkl文件保存读写
class pickle_operation():
    def __init__(self, now=None):
        now = datetime.datetime.now()
        self.now_start = now.strftime('%Y-%m-%d')
        self.ip_existence = ''.join([os.path.dirname(__file__), '\\myip_list.pkl'])

    # 写入文件
    def pickle_save(self, ip_list):
        # 判断文件是否存在，存在读取字典，不存在创建字典
        if os.path.exists(self.ip_existence):
            pickle_du = open(os.path.dirname(__file__)+'\\myip_list.pkl', 'rb')
            my_list = pickle.load(pickle_du)
            pickle_du.close()
        else:
            my_list = {}
        my_list[self.now_start] = ip_list
        pickle_file = open(os.path.dirname(__file__)+'\\myip_list.pkl', 'wb')
        pickle.dump(my_list, pickle_file)
        pickle_file.close()
        number_result = {'success':'更新成功'}
        return number_result

    # 读取文件
    def pickle_read(self, state, Interface=None, date=None):
        # state = Lately 查询最近
        # state = Ally 查询所有
        # state = Date 查询日期
        # Interface = 1 查询最近接口调用
        # date 查询日期接口调用
        if os.path.exists(self.ip_existence):
            pickle_du = open(os.path.dirname(__file__)+'\\myip_list.pkl', 'rb')
            my_list2 = pickle.load(pickle_du)
            pickle_du.close()
        else:
            print(1)
            number_result = {'fail':'查询为空,请先更新'}
            return json.dumps(number_result)
        if state == 'Lately':
            number = sorted(my_list2.keys())[len(my_list2)-1]
            number_list = my_list2[number]
            if Interface == 1:
                number_result = {'代理IP': number_list}
            else:
                number_result = {'最近更新日期': number, '代理IP': number_list}
        elif state == 'Ally':
            number_result = my_list2
        elif state == 'Date':
            if date is None:
                date = input('请输入要查询的日期(格式:%Y-%M-%D)：')
            if date in my_list2.keys():
                number_result = {'代理IP': my_list2[date]}
            else:
                number_result = {'fail':'填写日期有误，请重新填写'}
        return json.dumps(number_result)


# 爬代理
class ip_Crawler():
    def __init__(self, url='http://www.xicidaili.com/'):
        self.header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86 Safari/537.36'}
        self.html = requests.get(url, headers=self.header)
    def ip_start(self):
        soup = BeautifulSoup(self.html.text, "html5lib")
        ip_result = []
        ip_dict = {}
        i = 0
        for each in soup.find_all('tr', class_='odd'):
            ip_gao = str(each.select('td')[4].text)
            if ip_gao == '高匿':
                ip_http = str(each.select('td')[5].text)
                ip_zhu = str(each.select('td')[1].text)
                ip_zhong = str(each.select('td')[2].text)
                ip_list = ''.join([ip_zhu, ':', ip_zhong])
                ip_dict = {ip_http: ip_list}
                ip_result.append(ip_dict)
            i = i + 1
            if i == 15:
                list_ip = len(ip_result)
                print('已爬取%s 个ip...' % list_ip)
                print('---检测是否可用---')
                list_ip_last = ip_testing(ip_result, header=self.header)
                list_ip = len(list_ip_last)
                print('检测到%s 个可用ip...' % list_ip)
                if list_ip == 0:
                    result = {'fail':'无可用IP'}
                else:
                    result =pickle_operation().pickle_save(list_ip_last)
                return(json.dumps(result))


# 检测代理ip是否可用
def ip_testing(ip_list, header):
    result_last = []
    a = 1
    my_ip = myself_ip(header)
    for i in ip_list:
        result ={}
        ip_http = sorted(i.keys())[0]
        ip_zhu = sorted(i.values())[0]
        proxy_support = {ip_http: ip_zhu}
        url = 'http://ip.chinaz.com/getip.aspx'
        r = requests.get(url, headers=header, proxies=proxy_support)
        a += 1
        if r.text == my_ip:
            continue
        else:
            result[ip_http] = ip_zhu
            result_last.append(result)        
    return result_last


# 查询自己的ip
def myself_ip(header):
    url = 'http://ip.chinaz.com/getip.aspx'
    html = requests.get(url, headers=header)
    return html.text


def inivate(num):
    # 更新代理
    if num == '1':
        print('---爬取今日的高匿代理ip---')
        ip_move = ip_Crawler().ip_start()
        result = pickle_operation().pickle_save(ip_move)
    # 查询最近 lately
    elif num == '2':
        result = pickle_operation().pickle_read('Lately')
    # 查询所有 ally
    elif num == '3':
        result = pickle_operation().pickle_read('Ally')
    # 查询日期 Date
    elif num == '4':
        result = pickle_operation().pickle_read('Date')
    else:
        print('输入错误')
        result = ''
    if result is not False:
        return json.loads(result)


if __name__ == '__main__':
    while True:
        class_pretty()
        num = input("序号 =>  ")
        if num_judge(num) is False or num_Range(num) is False:
            print('请输入正确序号')
            continue
        else:
            result_json = inivate(num)
        if result_json is None:
            continue
        if num == '2':
            keys_data = sorted(result_json.keys())[1]
            keys_ip = sorted(result_json.keys())[0]
            result_data = ''.join([keys_data, ' => ', result_json[keys_data]])
            result_ip = ''.join([keys_ip, ' => ', str(result_json[keys_ip])])
            print(result_data)
            print(result_ip)
        elif num == '3' or num == '1':
            print(result_json)
        elif num == '4':
            keys_data01 = sorted(result_json.keys())[0]
            result_dately = ''.join([keys_data01, ' => ', str(result_json[keys_data01])])
            print(result_dately)
        print('')
